<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"chuangges.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="混合开发、适配方案、flex 布局、事件类型">
<meta property="og:type" content="article">
<meta property="og:title" content="移动端开发">
<meta property="og:url" content="https://chuangges.gitee.io/2019/06/24/8-1-%E7%A7%BB%E5%8A%A8%E7%AB%AF%E5%BC%80%E5%8F%91/index.html">
<meta property="og:site_name" content="闯哥要去流浪了">
<meta property="og:description" content="混合开发、适配方案、flex 布局、事件类型">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://chuangges.gitee.io/images/mobile/Responsive.png">
<meta property="og:image" content="https://chuangges.gitee.io/images/mobile/flex.png">
<meta property="og:image" content="https://chuangges.gitee.io/images/mobile/grail.png">
<meta property="article:published_time" content="2019-06-23T18:03:23.000Z">
<meta property="article:modified_time" content="2024-01-22T06:28:46.895Z">
<meta property="article:author" content="chuangges">
<meta property="article:tag" content="移动端开发">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://chuangges.gitee.io/images/mobile/Responsive.png">

<link rel="canonical" href="https://chuangges.gitee.io/2019/06/24/8-1-%E7%A7%BB%E5%8A%A8%E7%AB%AF%E5%BC%80%E5%8F%91/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>移动端开发 | 闯哥要去流浪了</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

<link rel="alternate" href="/atom.xml" title="闯哥要去流浪了" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">闯哥要去流浪了</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">愿你岁月可回首，且以深情共白头</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://chuangges.gitee.io/2019/06/24/8-1-%E7%A7%BB%E5%8A%A8%E7%AB%AF%E5%BC%80%E5%8F%91/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/chuang.png">
      <meta itemprop="name" content="chuangges">
      <meta itemprop="description" content="chuangge's blog.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="闯哥要去流浪了">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          移动端开发
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2019-06-24 02:03:23" itemprop="dateCreated datePublished" datetime="2019-06-24T02:03:23+08:00">2019-06-24</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2024-01-22 14:28:46" itemprop="dateModified" datetime="2024-01-22T14:28:46+08:00">2024-01-22</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E5%BC%80%E5%8F%91/" itemprop="url" rel="index"><span itemprop="name">移动端开发</span></a>
                </span>
            </span>

          <br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>23k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>21 分钟</span>
            </span>
            <div class="post-description">混合开发、适配方案、flex 布局、事件类型</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h1 id="一、开发技术"><a href="#一、开发技术" class="headerlink" title="一、开发技术"></a>一、开发技术</h1><h2 id="应用类型"><a href="#应用类型" class="headerlink" title="应用类型"></a>应用类型</h2><blockquote>
<p><code>Android / IOS 原生应用</code>分别基于 Java&#x2F;Kotlin、Objective-c&#x2F;Swift 语言调用工具包 SDK，<code>Web 网页应用</code>是将 Vue&#x2F;React&#x2F;Angular 编写的单页应用打包后生成的 Html 部署到服务器，<code>Hybrid 混合应用</code>则是通过原生语言编写应用外壳并在 webview 内嵌动态 H5，然后通过 JSBridge 接口来实现运行环境隔离的 Native JS 通信机制 (类似远程过程调用 RPC)。</p>
</blockquote>
<table>
<thead>
<tr>
<th></th>
<th>主要特点</th>
<th>运行环境</th>
</tr>
</thead>
<tbody><tr>
<td>桌面应用</td>
<td>鼠标和键盘交互、多种安装方式、系统功能需要权限</td>
<td>Window、macOS、Linux 电脑</td>
</tr>
<tr>
<td>移动应用</td>
<td>触摸屏和手势交互、安装包下载更新、支持系统功能</td>
<td>Android、IOS 手机&#x2F;平板设备</td>
</tr>
<tr>
<td>Web 应用</td>
<td>无需安装、跨平台、服务端更新、不可调用系统功能</td>
<td>浏览器、Webview、WKWebView</td>
</tr>
<tr>
<td>– 内嵌应用</td>
<td>–</td>
<td>–</td>
</tr>
<tr>
<td>小程序</td>
<td>无需安装、用完即走、内置的轻应用</td>
<td>微信、抖音、支付宝等平台</td>
</tr>
<tr>
<td>Light 快应用</td>
<td>无需安装、原生体验、用于试用推送</td>
<td>参与统一标准的厂商安卓手机</td>
</tr>
<tr>
<td>PWA 渐进应用</td>
<td>无需安装、web 网页、离线&#x2F;通知&#x2F;推送</td>
<td>浏览器、IOS 环境需要适配</td>
</tr>
<tr>
<td>App Clips</td>
<td>Apple 轻应用、用于预览试用</td>
<td>NFC 扫描、点击链接等触发</td>
</tr>
<tr>
<td>–</td>
<td>–</td>
<td></td>
</tr>
<tr>
<td>常见应用</td>
<td>开发方案</td>
<td>跨平台框架</td>
</tr>
<tr>
<td>桌面应用</td>
<td>原生语言、托管平台、Web 开发客户端</td>
<td>QT、NW.js、Electron、Tauri</td>
</tr>
<tr>
<td>移动应用</td>
<td>Web 网页、Native 原生、Hybrid 混合</td>
<td>ReactNative、Weex、Flutter</td>
</tr>
<tr>
<td>小程序</td>
<td>微信小程序原生、跨端则通过框架转换代码</td>
<td>Uniapp、Taro、Antmove</td>
</tr>
</tbody></table>
<h2 id="跨平台方案"><a href="#跨平台方案" class="headerlink" title="跨平台方案"></a>跨平台方案</h2><blockquote>
<p><code>小程序</code> 使用了定制化 JSBridge 并通过 WebView 双线程模式隔离了 JS 逻辑和 UI 渲染、<code>ReactNative/Weex</code> 将元素解析为原生标签后传递到原生应用去渲染但是将渲染引擎集成到框架导致打包体积较大、<code>快应用</code>参考小程序采用 JS 开发并将渲染引擎集成到只读存储器 ROM 而无需打包、<code>自绘引擎</code>采用预先编译的 AOT 模式相比其它的 JIT 动态即时编译性能较好。 </p>
</blockquote>
<table>
<thead>
<tr>
<th>渲染方案</th>
<th>主要特点</th>
<th>框架代表</th>
</tr>
</thead>
<tbody><tr>
<td>WebView</td>
<td>Hybrid 混合模式、内嵌动态更新并跨平台的 H5</td>
<td>Cordova、Ionic、小程序</td>
</tr>
<tr>
<td>原生组件</td>
<td>解析器根据不同平台将虚拟 DOM 映射为原生标签</td>
<td>ReactNative、Weex、快应用</td>
</tr>
<tr>
<td>自绘引擎</td>
<td>抛弃原生组件并自定义渲染引擎、不支持动态更新</td>
<td>QT、Flutter、Unity</td>
</tr>
</tbody></table>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// JS 调用原生接口获取手机型号：定义原生接口、JSBridge 注册、JS 调用</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">JSAPI</span>&#123;</span><br><span class="line">    @<span class="title class_">JavascriptInterface</span></span><br><span class="line">    public <span class="title class_">Object</span> <span class="title function_">getPhoneModel</span>(<span class="params"><span class="built_in">Object</span> msg</span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Build</span>.<span class="property">MODEL</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> wendu.<span class="property">dsbridge</span>.<span class="property">DWebView</span></span><br><span class="line"><span class="title class_">DWebView</span> dwebView = (<span class="title class_">DWebView</span>) <span class="title function_">findViewById</span>(R.<span class="property">id</span>.<span class="property">dwebview</span>);</span><br><span class="line">dwebView.<span class="title function_">addJavascriptObject</span>(<span class="keyword">new</span> <span class="title class_">JsAPI</span>(), <span class="literal">null</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> dsBridge = <span class="built_in">require</span>(<span class="string">&quot;dsbridge&quot;</span>)</span><br><span class="line"><span class="keyword">var</span> model = dsBridge.<span class="title function_">call</span>(<span class="string">&quot;getPhoneModel&quot;</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(model);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 混合开发方案：Ionic + Angular + Capacitor/Cordova</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> Ionic：基于 Angular 扩展的组件库，可构建原生体验的应用。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> Angular：可独立开发应用的 JS 库，用于开发 web H5 应用。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> Capacitor：编写应用壳，用于将 H5 应用编译打包为原生应用</span></span><br><span class="line"><span class="comment"> * 对之前的 Cordova 作出了兼容优化，已成为 ionic4+ 默认的打包工具。</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 环境搭建</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 1、安装脚手架：ionic5 -- ionic、ionic6 -- <span class="doctag">@ionic</span>/cli</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 2、android 环境配置：Java JDK、android studio 等工具</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 3、Ionic 指令搭建项目：调试打包、新建应用、集成原生环境等</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line">cnpm i -g @angular/cli @ionic/cli typescript</span><br><span class="line"></span><br><span class="line">ionic start ionic-angular tabs/blank/sidemenu</span><br><span class="line">ionic serve    <span class="comment">// 电脑运行：电脑端 localhost 访问</span></span><br><span class="line">ionic build    <span class="comment">// 编译打包：生成文件夹 www</span></span><br><span class="line">ionic serve --external --host=<span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span>   <span class="comment">// 手机浏览器调试</span></span><br><span class="line"></span><br><span class="line">cd ionic-angular</span><br><span class="line">cnpm i @capacitor/ios @capacitor/android</span><br><span class="line">npx cap init [appName] [appId]      <span class="comment">// 配置应用名称和包名</span></span><br><span class="line">npx cap add ios                     <span class="comment">// 生成文件夹 ios </span></span><br><span class="line">npx cap add android                 <span class="comment">// 生成文件夹 android</span></span><br></pre></td></tr></table></figure>



<h2 id="WebView"><a href="#WebView" class="headerlink" title="WebView"></a>WebView</h2><blockquote>
<p>原生应用中<code>渲染 html、通信 JS</code> 的浏览器自带组件，浏览器内核则是支持浏览器运行的核心程序，可分为<code>渲染引擎 WebCore / Blink、脚本引擎 JSCore / V8</code>。国外手机的浏览器是 chrome，国内的则因为版权是厂商基于 <code>webkit / chromium / 第三方</code> 定制的。</p>
</blockquote>
<table>
<thead>
<tr>
<th>浏览器内核</th>
<th>主要特点</th>
<th>应用场景</th>
</tr>
</thead>
<tbody><tr>
<td>Trident &#x2F; EdgeHTML</td>
<td>IE10 前后、兼容性好、只能用于 Window</td>
<td>IE、Edge、百度</td>
</tr>
<tr>
<td>Gecko</td>
<td>速度快、跨平台支持 Window&#x2F;Linux&#x2F;MacOs</td>
<td>Firefox</td>
</tr>
<tr>
<td>Webkit</td>
<td>苹果基于 KHTML 开发、解析速度快、容错差</td>
<td>Safari、Android</td>
</tr>
<tr>
<td>Chromium &#x2F; Blink</td>
<td>谷歌基于 webkit 开发、Blink 是渲染引擎</td>
<td>chrome、华为等国产</td>
</tr>
<tr>
<td>Trident + Blink</td>
<td>IE 兼容模式、Webkit &#x2F; Blink 极速模式</td>
<td>搜狗、UC、QQ、360</td>
</tr>
<tr>
<td>– WebView 内核</td>
<td>–</td>
<td>–</td>
</tr>
<tr>
<td>webkit &#x2F; chromium</td>
<td>android4.4 前后的原生默认内核</td>
<td>浏览器、小程序</td>
</tr>
<tr>
<td>X5 内核、Crosswalk</td>
<td>android 可集成的第三方优化内核</td>
<td>微信等腾讯应用</td>
</tr>
<tr>
<td>UIWebView&#x2F;WKWebView</td>
<td>ios12 版本前后的原生默认内核</td>
<td>苹果浏览器、小程序</td>
</tr>
</tbody></table>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1、应用权限配置：访问网络数据，需要在 AndroidManifest 添加网络权限。</span></span><br><span class="line">&lt;uses-permission <span class="attr">android</span>:name=<span class="string">&quot;android.permission.INTERNET&quot;</span> /&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、xml 布局文件中添加 WebView 控件</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">WebView</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">android:id</span>=<span class="string">&quot;@+id/webview&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">android:layout_width</span>=<span class="string">&quot;match_parent&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="language-xml">    <span class="attr">android:layout_height</span>=<span class="string">&quot;match_parent&quot;</span> </span></span></span><br><span class="line"><span class="tag"><span class="language-xml">/&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、WebView 网页加载：build.gradle 配置绑定 viewBinding &#123;enabled = true&#125;</span></span><br><span class="line">public final <span class="keyword">class</span> <span class="title class_">Demo1Activity</span> <span class="keyword">extends</span> <span class="title class_ inherited__">AppCompatActivity</span> &#123;</span><br><span class="line"></span><br><span class="line">    private <span class="title class_">ActivityDemo1Binding</span> binding;</span><br><span class="line"></span><br><span class="line">    @<span class="title class_">Override</span></span><br><span class="line">    protected <span class="keyword">void</span> <span class="title function_">onCreate</span>(<span class="params">Bundle savedInstanceState</span>) &#123;</span><br><span class="line">        <span class="variable language_">super</span>.<span class="title function_">onCreate</span>(savedInstanceState);</span><br><span class="line">        binding = <span class="title class_">ActivityDemo1Binding</span>.<span class="title function_">inflate</span>(<span class="title function_">getLayoutInflater</span>());</span><br><span class="line">        <span class="title function_">setContentView</span>(binding.<span class="title function_">getRoot</span>());</span><br><span class="line">        <span class="comment">// 获取 WebView 设置对象、设置支持 JavaScript、打开百度页面</span></span><br><span class="line">        <span class="title class_">WebSettings</span> settings = binding.<span class="property">webview</span>.<span class="title function_">getSettings</span>();</span><br><span class="line">        settings.<span class="title function_">setJavaScriptEnabled</span>(<span class="literal">true</span>);</span><br><span class="line">        binding.<span class="property">webview</span>.<span class="title function_">loadUrl</span>(<span class="string">&quot;https://www.baidu.com&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="JSBridge"><a href="#JSBridge" class="headerlink" title="JSBridge"></a>JSBridge</h2><blockquote>
<p>WebView JavaScript Bridge，通过 JS 实现并用于构建 JS Native 双向通信的交互接口，比如微信的 JS-SDK、wx 对象。引用方法有两种：<code>H5 npm 本地安装</code>但需维护版本、<code>Native 注入</code>但在使用前需判断是否注入成功。通信机制主要内容有：JS 发送消息来调用查看相册等系统功能和通知状态、Native 发送消息来回溯调用结果和消息推送，其实现原理如下：</p>
</blockquote>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 一、JS 调用 Native</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 注入 API：通过 WebView 的接口向 JS Context 注入对象或方法。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 拦截 URL Scheme：通过 Native 拦截前端请求并根据链接参数操作。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> 重写 prompt：监听方法 onJsPrompt/onJsConfirm/onJsAlert。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* <span class="doctag">@title</span> 1-1、Android4.2+ 推荐的注入方式</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> H5 调用一：window.JSBridge.foo();         // foo</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> H5 调用二：window.JSBridge.foo2(&#x27;test&#x27;);  // foo2:test</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line">webSettings = mWebView.<span class="title function_">getSettings</span>();  </span><br><span class="line">webSettings.<span class="title function_">setJavaScriptEnabled</span>(<span class="literal">true</span>);</span><br><span class="line">mWebView.<span class="title function_">addJavascriptInterface</span>(<span class="title function_">getJSBridge</span>(), <span class="string">&quot;JSBridge&quot;</span>);</span><br><span class="line">private <span class="title class_">Object</span> <span class="title function_">getJSBridge</span>(<span class="params"></span>)&#123;  </span><br><span class="line">    <span class="title class_">Object</span> insertObj = <span class="keyword">new</span> <span class="title class_">Object</span>()&#123;  </span><br><span class="line">        @<span class="title class_">JavascriptInterface</span></span><br><span class="line">        public <span class="title class_">String</span> <span class="title function_">foo</span>(<span class="params"></span>)&#123;  </span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;foo&quot;</span>;  </span><br><span class="line">        &#125;  </span><br><span class="line"></span><br><span class="line">        @<span class="title class_">JavascriptInterface</span></span><br><span class="line">        public <span class="title class_">String</span> <span class="title function_">foo2</span>(<span class="params">final <span class="built_in">String</span> param</span>)&#123;  </span><br><span class="line">            <span class="keyword">return</span> <span class="string">&quot;foo2:&quot;</span> + param;  </span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">    <span class="keyword">return</span> insertObj;  </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* <span class="doctag">@title</span> 1-2、Ios7+ 注入：top 确保调用到最顶级</span></span><br><span class="line"><span class="comment">* <span class="doctag">@param</span> H5 调用：window.top.foo(&#x27;test&#x27;);    // &#x27;foo:test&#x27;</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line">#<span class="keyword">import</span> &lt;<span class="title class_">JavaScriptCore</span>/<span class="title class_">JavaScriptCore</span>.<span class="property">h</span>&gt;</span><br><span class="line"></span><br><span class="line">-(<span class="keyword">void</span>)<span class="attr">webViewDidFinishLoad</span>:(<span class="title class_">UIWebView</span> *)webView&#123;</span><br><span class="line">    [self hideProgress];</span><br><span class="line">    [self setJSInterface];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">-(<span class="keyword">void</span>)setJSInterface&#123;</span><br><span class="line"></span><br><span class="line">    <span class="title class_">JSContext</span> *context =[_wv <span class="attr">valueForKeyPath</span>:</span><br><span class="line">        @<span class="string">&quot;documentView.webView.mainFrame.javaScriptContext&quot;</span>];</span><br><span class="line"></span><br><span class="line">    context[@<span class="string">&quot;foo&quot;</span>] = ^() &#123;</span><br><span class="line">        <span class="title class_">NSArray</span> *args = [<span class="title class_">JSContext</span> currentArguments];</span><br><span class="line">        <span class="title class_">NSString</span> *title = [<span class="title class_">NSString</span> <span class="attr">stringWithFormat</span>:@<span class="string">&quot;%@&quot;</span>,</span><br><span class="line">            [args <span class="attr">objectAtIndex</span>:<span class="number">0</span>]];</span><br><span class="line">        <span class="keyword">return</span> [<span class="title class_">NSString</span> <span class="attr">stringWithFormat</span>:@<span class="string">&quot;foo:%@&quot;</span>, title];</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 2、Android、IOS 拦截 URL Scheme：方便 app 调用的链接，比如 weixin://。</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">location</span>.<span class="property">href</span> = <span class="string">&quot;js://getInfo&quot;</span>;  <span class="comment">// H5 发送 Scheme 请求等待拦截</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">nativeInfo</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123; &#125;  ;  <span class="comment">// H5 接收请求被拦截后的执行结果</span></span><br><span class="line"></span><br><span class="line">public boolean <span class="title function_">shouldOverrideUrlLoading</span>(<span class="params">WebView view, <span class="built_in">String</span> url</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (url.<span class="title function_">equals</span>(<span class="string">&quot;js://getInfo&quot;</span>)) &#123;</span><br><span class="line">        view.<span class="title function_">loadUrl</span>(<span class="string">&quot;javascript:nativeInfo(&quot;</span> + json + <span class="string">&quot;);&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">- (<span class="variable constant_">BOOL</span>)<span class="attr">webView</span>:(<span class="title class_">UIWebView</span> *)webView shouldStartLoadWithRequest</span><br><span class="line">:(<span class="title class_">NSURLRequest</span> *) request <span class="attr">navigationType</span>:(<span class="title class_">UIWebViewNavigationType</span>)</span><br><span class="line">navigationType &#123;  <span class="comment">// 加载前的预判断</span></span><br><span class="line">    <span class="variable constant_">NSURL</span> *url = [request <span class="variable constant_">URL</span>];</span><br><span class="line">    <span class="title class_">NSString</span> *requestString = [[request <span class="variable constant_">URL</span>] absoluteString];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3、Android4.2- 推荐的重写 prompt：拦截后自定义逻辑</span></span><br><span class="line">@<span class="title class_">Override</span>   <span class="comment">// 标注重写方法</span></span><br><span class="line">public boolean <span class="title function_">onJsPrompt</span>(<span class="params"></span></span><br><span class="line"><span class="params">    WebView view, </span></span><br><span class="line"><span class="params">    <span class="built_in">String</span> url, </span></span><br><span class="line"><span class="params">    <span class="built_in">String</span> message,</span></span><br><span class="line"><span class="params">    <span class="built_in">String</span> defaultValue,</span></span><br><span class="line"><span class="params">    JsPromptResult result,</span></span><br><span class="line"><span class="params"></span>)&#123;</span><br><span class="line">    result.<span class="title function_">confirm</span>(<span class="title class_">JSBridge</span>.<span class="title function_">callJava</span>(view, message));</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@title</span> 二、Native 调用 H5</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> Android：JS 方法必须暴露给全局 window。</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> IOS：JS 方法必须暴露给全局 window.top。</span></span><br><span class="line"><span class="comment">**/</span></span><br><span class="line"><span class="variable language_">window</span>.<span class="property">callAndroid</span> = <span class="keyword">function</span>(<span class="params"></span>) &#123; &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 4.4 版本之前：无法获取返回值，需要在 UI 线程运行</span></span><br><span class="line">webView = <span class="keyword">new</span> <span class="title class_">WebView</span>(<span class="variable language_">this</span>);     </span><br><span class="line">webView.<span class="title function_">loadUrl</span>(<span class="string">&quot;javascript: method(data)&quot;</span>); </span><br><span class="line"><span class="comment">// 4.4 及以后：value 就是对应 JS 方法的返回值 </span></span><br><span class="line">webView.evaluateJavascript(<span class="string">&quot;javascript: method(data)&quot;</span>, </span><br><span class="line">  <span class="keyword">new</span> <span class="title class_">ValueCallback</span>&lt;<span class="title class_">String</span>&gt;() &#123;</span><br><span class="line">      @<span class="title class_">Override</span></span><br><span class="line">      public <span class="keyword">void</span> <span class="title function_">onReceiveValue</span>(<span class="params"><span class="built_in">String</span> value</span>) &#123;  &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// UIWebview、WKWebview</span></span><br><span class="line">webview.<span class="title function_">stringByEvaluatingJavaScriptFromString</span>(<span class="string">&quot;method(data)&quot;</span>)</span><br><span class="line">[jsContext <span class="attr">evaluateJavaScript</span>:@<span class="string">&quot;method(ev, data)&quot;</span>]</span><br></pre></td></tr></table></figure>


<h1 id="二、适配方案"><a href="#二、适配方案" class="headerlink" title="二、适配方案"></a>二、适配方案</h1><blockquote>
<p>让页面能在不同尺寸和分辨率的移动设备上尽可能的实现合理展示，设计图都是 2 倍的，这是因为页面中除了字体是矢量图而大部分都是位图。如果 1px 宽高的盒子里放入 1px 宽高的图片则图片会失真，因为在移动端渲染时是用 4px 渲染。</p>
</blockquote>
<ul>
<li><strong>设备像素</strong>：物理像素，通常指设备的分辨率。单位 dp，是设备能控制显示的最小单位。主要特点是：同一个设备的 1dp 长度是固定不变的、DPR 设备像素比取决于是否高清等屏幕特性和缩放比例。页面放大时内容减少是因为 1px 等于更多的设备像素。</li>
<li><strong>CSS 像素</strong>：逻辑像素，主要用于精确度量浏览器的 Web 页面。单位 px，是独立于设备而用于开发的抽象单位。主要特点是：改变大小的场景有缩放屏幕、更换设备。同样代码在不同分辨率的设备中显示一致是因为移动设备根据各自像素比转换成了设备像素。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 设备判断：微信、支付宝、移动端、Ios、Android</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">isWechat</span>: navigator.<span class="property">userAgent</span>.<span class="title function_">toLowerCase</span>().<span class="title function_">indexOf</span>(<span class="string">&quot;micromessenger&quot;</span>) &gt; -<span class="number">1</span>,</span><br><span class="line">  <span class="attr">isAlipay</span>: navigator.<span class="property">userAgent</span>.<span class="title function_">toLowerCase</span>().<span class="title function_">indexOf</span>(<span class="string">&quot;alipay&quot;</span>) &gt; -<span class="number">1</span>,  </span><br><span class="line">  isMobile = <span class="regexp">/Android|webOS|iPhone|iPod|BlackBerry/i</span>.<span class="title function_">test</span>(navigator.<span class="property">userAgent</span>),</span><br><span class="line">  <span class="attr">isIOS</span>: <span class="regexp">/iPhone|iPad|iPod/i</span>.<span class="title function_">test</span>(navigator.<span class="property">userAgent</span>),</span><br><span class="line">  <span class="attr">isAndroid</span>: <span class="regexp">/Android/i</span>.<span class="title function_">test</span>(navigator.<span class="property">userAgent</span>),</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 启用360浏览器的极速模式 (webkit)  </span></span><br><span class="line">&lt;meta name=<span class="string">&quot;renderer&quot;</span> content=<span class="string">&quot;webkit&quot;</span> /&gt;</span><br><span class="line"><span class="comment">// 优先使用 IE 最新版本和 Chrome  </span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">http-equiv</span>=<span class="string">&quot;X-UA-Compatible&quot;</span> <span class="attr">content</span>=<span class="string">&quot;IE=EDGE, chrome=1&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="comment">// 页面窗口自动调整到设备宽度，并禁止用户缩放页面 (scale) </span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, height=device-height, </span></span></span></span><br><span class="line"><span class="string"><span class="tag"><span class="language-xml">initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="comment">// 使用全屏模式运行，仅针对 ios safari  </span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;apple-mobile-web-app-capable&quot;</span> <span class="attr">content</span>=<span class="string">&quot;yes&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="comment">// 设置顶端状态栏背景为灰色半透明，仅针对 ios safari  </span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;apple-mobile-web-app-status-bar-style&quot;</span> <span class="attr">content</span>=<span class="string">&quot;black-translucent&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="comment">// windows phone 点击无高光 </span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;msapplication-tap-highlight&quot;</span> <span class="attr">content</span>=<span class="string">&quot;no&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="comment">// 关闭电话号码和邮箱的自动识别  </span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;format-detection&quot;</span> <span class="attr">content</span>=<span class="string">&quot;telephone=no, email=no&quot;</span> /&gt;</span></span></span><br></pre></td></tr></table></figure>


<h2 id="Viewport-缩放"><a href="#Viewport-缩放" class="headerlink" title="Viewport 缩放"></a>Viewport 缩放</h2><ul>
<li><strong>Viewport</strong>：浏览器上用来显示网页的部分区域，是手机浏览器的实际宽度。注意移动设备默认的是布局视口，但是移动端开发时需要的是理想视口，视口控制通过只对移动端有效的 meta 实现：设备宽度 &#x3D; 页面宽度 &#x3D; 浏览器视口宽度。</li>
<li><strong>浏览器宽度</strong>：PC 端网站都是以浏览器窗口(设备屏幕) 作为视口进行布局，但是手机浏览器的实际宽度默认比手机屏幕宽，手机浏览器内部的宽度始终是本身 viewport 而无论手机宽度是 320px&#x2F;640px。手机浏览器的设计页面为了让浏览桌面端网页时显示正常一般基于 960px，但这样会使手机浏览器出现横向滚动条，所以移动端浏览器会自动将视口缩放到移动端窗口的大小，网页内容看起来被压扁而不容易观看。可简单理解为：<strong>当浏览器宽度小于 980 时，viewport 宽度为980，大于 980 时则和 viewport 宽度一致</strong>。</li>
<li>分类：<strong>布局视口</strong> (手机浏览器的实际区域，用于计算 CSS 页面布局)、<strong>视觉视口</strong> (用户当前看到的区域，放大页面时内容减少但并不会受影响)、<strong>理想视口</strong> (移动设备的屏幕区域，它以 CSS 单位计算并与设备的物理宽高无关)。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 针对不同屏幕分辨率的手机设置等比例缩放。简单方便，但是 PC 端可能会界面变形、像素失真。</span></span><br><span class="line">&lt;meta name=<span class="string">&quot;viewport&quot;</span> content=<span class="string">&quot;width=device-width, height=device-height, </span></span><br><span class="line"><span class="string">  initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no&quot;</span> /&gt;</span><br></pre></td></tr></table></figure>


<h2 id="Responsive-响应式"><a href="#Responsive-响应式" class="headerlink" title="Responsive 响应式"></a>Responsive 响应式</h2><blockquote>
<p>设计理念通过媒体查询根据不同的屏幕分辨率来进行适配，从而在不同设备不同分辨率下都有良好的用户体验，一般通过媒体查询设置移动端宽度。缺点是 无法覆盖全部分辨率、代码量大且维护性难、安卓机型问题较多，一般只适合简单的资讯类页面。</p>
</blockquote>
  <div align="center">
      <img src="" data-original="/images/mobile/Responsive.png" alt="flex 布局" width="100%">
  </div>

  <figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 法一 */</span> </span><br><span class="line">link media=&quot;(<span class="attribute">max-width</span>:<span class="number">480px</span>)<span class="string">&quot; href=&quot;</span>mobile.css<span class="string">&quot;</span></span><br><span class="line"><span class="string">	</span></span><br><span class="line"><span class="string">/* 法二 */ </span></span><br><span class="line"><span class="string">@media all and (orientation :landscape) &#123;  /* 横屏 */  &#125; </span></span><br><span class="line"><span class="string">@media all and (orientation :portrait) &#123;  /* 竖屏 */  &#125;</span></span><br><span class="line"><span class="string">@media screen and (max-width: 500px) &#123;  </span></span><br><span class="line"><span class="string">   body &#123; background: black &#125;</span></span><br><span class="line"><span class="string">&#125;</span></span><br></pre></td></tr></table></figure>


<h2 id="Adaptive-自适应"><a href="#Adaptive-自适应" class="headerlink" title="Adaptive 自适应"></a>Adaptive 自适应</h2><blockquote>
<p>使容器子元素的宽高能够最合理的方式填充空间。</p>
</blockquote>
<ul>
<li><strong>百分比布局</strong>：宽度自适应而在不同分辨率下都能适配，但需要根据确定的父级元素计算。width、height 等相对于直接父元素。translate、background-size 等相对于自身。</li>
<li><strong>vw、vh 布局</strong>：换算为相对视口的宽高而实现自适应，但计算量大而且可能出现小数。</li>
<li><strong>scale 布局</strong>：根据屏幕和设计图的比例进行等比缩放，但可能有周边留白、字体模糊。</li>
<li><strong>rem 布局</strong>：通过动态设置根元素字号而实现适配，适用于宽高比不固定的应用。</li>
</ul>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br></pre></td><td class="code"><pre><span class="line">=================== 一、vw vh ====================</span><br><span class="line"></span><br><span class="line"><span class="comment">// css 方案：util.scss/less、vue.config.js、home.vue</span></span><br><span class="line">@use <span class="string">&quot;sass:math&quot;</span>;</span><br><span class="line"><span class="attr">$designWidth</span>: <span class="number">1920</span>;</span><br><span class="line"><span class="attr">$designHeight</span>: <span class="number">1080</span>;</span><br><span class="line">@<span class="keyword">function</span> <span class="title function_">vw</span>(<span class="params">$px</span>) &#123;</span><br><span class="line">    @<span class="keyword">return</span> math.<span class="title function_">div</span>($px, $designWidth) * 100vw;</span><br><span class="line">&#125;</span><br><span class="line">@<span class="keyword">function</span> <span class="title function_">vh</span>(<span class="params">$px</span>) &#123;</span><br><span class="line">    @<span class="keyword">return</span> math.<span class="title function_">div</span>($px, $designHeight) * 100vh;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@charset <span class="string">&quot;utf-8&quot;</span>;</span><br><span class="line">@<span class="attr">designWidth</span>: <span class="number">1920</span>;</span><br><span class="line">@<span class="attr">designHeight</span>: <span class="number">1080</span>;</span><br><span class="line">.<span class="title function_">px2vw</span>(<span class="params">@name, @px</span>) &#123;</span><br><span class="line">    @&#123;name&#125;: (@px / @designWidth) * 100vw;</span><br><span class="line">&#125;</span><br><span class="line">.<span class="title function_">px2vh</span>(<span class="params">@name, @px</span>) &#123;</span><br><span class="line">    @&#123;name&#125;: (@px / @designHeight) * 100vh;</span><br><span class="line">&#125;</span><br><span class="line">.<span class="title function_">px2font</span>(<span class="params">@px</span>) &#123;</span><br><span class="line">    font-<span class="attr">size</span>: (@px / @designWidth) * 100vw;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">&quot;path&quot;</span>);</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">resolve</span>(<span class="params">dir</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> path.<span class="title function_">join</span>(__dirname, dir);</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">    <span class="attr">publicPath</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">    <span class="attr">configureWebpack</span>: &#123;</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&quot;app name&quot;</span>,</span><br><span class="line">        <span class="attr">resolve</span>: &#123; <span class="attr">alias</span>: &#123; <span class="string">&quot;@&quot;</span>: <span class="title function_">resolve</span>(<span class="string">&quot;src&quot;</span>) &#125; &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">css</span>: &#123;</span><br><span class="line">        <span class="comment">// 全局配置 utils.scss：</span></span><br><span class="line">        <span class="attr">loaderOptions</span>: &#123;</span><br><span class="line">            <span class="attr">sass</span>: &#123; <span class="attr">prependData</span>: <span class="string">`@import &quot;@/styles/utils.scss&quot;;`</span> &#125;,</span><br><span class="line">            <span class="attr">less</span>: &#123; <span class="attr">additionalData</span>: <span class="string">`@import &quot;@/styles/utils.less&quot;;`</span> &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">.<span class="property">box</span>&#123;</span><br><span class="line">    <span class="attr">width</span>: <span class="title function_">vw</span>(<span class="number">300</span>);</span><br><span class="line">    <span class="attr">height</span>: <span class="title function_">vh</span>(<span class="number">100</span>);</span><br><span class="line">    font-<span class="attr">size</span>: <span class="title function_">vh</span>(<span class="number">16</span>);</span><br><span class="line">    background-<span class="attr">color</span>: black;</span><br><span class="line">    margin-<span class="attr">left</span>: <span class="title function_">vw</span>(<span class="number">10</span>);</span><br><span class="line">    margin-<span class="attr">top</span>: <span class="title function_">vh</span>(<span class="number">10</span>);</span><br><span class="line">    <span class="attr">border</span>: <span class="title function_">vh</span>(<span class="number">2</span>) solid red;</span><br><span class="line">&#125;</span><br><span class="line">.<span class="property">box</span>&#123;</span><br><span class="line">    .<span class="title function_">px2vw</span>(width, <span class="number">300</span>);</span><br><span class="line">    .<span class="title function_">px2vh</span>(height, <span class="number">100</span>);</span><br><span class="line">    .<span class="title function_">px2font</span>(<span class="number">16</span>);</span><br><span class="line">    .<span class="title function_">px2vw</span>(margin-left, <span class="number">300</span>);</span><br><span class="line">    .<span class="title function_">px2vh</span>(margin-top, <span class="number">100</span>);</span><br><span class="line">    background-<span class="attr">color</span>: black;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// JS 方案</span></span><br><span class="line"><span class="keyword">const</span> designWidth = <span class="number">1920</span>;</span><br><span class="line"><span class="keyword">const</span> designHeight = <span class="number">1080</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">px2vw</span> = (<span class="params">_px</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> (_px * <span class="number">100.0</span>) / designWidth + <span class="string">&#x27;vw&#x27;</span>;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">px2vh</span> = (<span class="params">_px</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> (_px * <span class="number">100.0</span>) / designHeight + <span class="string">&#x27;vh&#x27;</span>;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">px2font</span> = (<span class="params">_px</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> (_px * <span class="number">100.0</span>) / designWidth + <span class="string">&#x27;vw&#x27;</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Echarts 字体、间距自适应：图表只支持具体像素</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">fitChartSize</span> = (<span class="params">size,defalteWidth = <span class="number">1920</span></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> clientWidth = <span class="variable language_">window</span>.<span class="property">innerWidth</span> || <span class="variable language_">document</span>.<span class="property">documentElement</span></span><br><span class="line">    .<span class="property">clientWidth</span> || <span class="variable language_">document</span>.<span class="property">body</span>.<span class="property">clientWidth</span>;</span><br><span class="line">    <span class="keyword">if</span> (!clientWidth) <span class="keyword">return</span> size;</span><br><span class="line">    <span class="keyword">let</span> scale = (clientWidth / defalteWidth);</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Number</span>((size*scale).<span class="title function_">toFixed</span>(<span class="number">3</span>));</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">fitChartFont</span> = fitChartSize;</span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span></span><br><span class="line"><span class="language-xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;chartsdom&quot;</span> <span class="attr">ref</span>=<span class="string">&quot;chart&quot;</span> <span class="attr">v-chart-resize</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">    <span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">name</span>: <span class="string">&quot;dashboardChart&quot;</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        <span class="attr">methods</span>: &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            <span class="title function_">getEchart</span>(<span class="params"></span>) &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                <span class="keyword">let</span> myChart = <span class="variable language_">this</span>.<span class="property">$echarts</span>.<span class="title function_">init</span>(<span class="variable language_">this</span>.<span class="property">$refs</span>.<span class="property">chart</span>);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                <span class="keyword">const</span> option = &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    <span class="attr">backgroundColor</span>: <span class="string">&quot;transparent&quot;</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    <span class="attr">tooltip</span>: &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                      <span class="attr">trigger</span>: <span class="string">&quot;item&quot;</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                      <span class="attr">formatter</span>: <span class="string">&quot;&#123;a&#125; &lt;br/&gt;&#123;b&#125; : &#123;c&#125;%&quot;</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    <span class="attr">grid</span>: &#123;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                      <span class="attr">left</span>: <span class="variable language_">this</span>.<span class="title function_">fitChartSize</span>(<span class="number">10</span>),</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                      <span class="attr">right</span>: <span class="variable language_">this</span>.<span class="title function_">fitChartSize</span>(<span class="number">20</span>),</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                      <span class="attr">top</span>: <span class="variable language_">this</span>.<span class="title function_">fitChartSize</span>(<span class="number">20</span>),</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                      <span class="attr">bottom</span>: <span class="variable language_">this</span>.<span class="title function_">fitChartSize</span>(<span class="number">10</span>),</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                      <span class="attr">containLabel</span>: <span class="literal">true</span>,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    &#125;,</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                    ...</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                &#125;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">                myChart.<span class="title function_">setOption</span>(option, <span class="literal">true</span>);</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">            &#125;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">        &#125;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml">    &#125;</span></span></span><br><span class="line"><span class="language-javascript"><span class="language-xml"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// postcss.config.js：适配插件 npm i postcss-px-to-viewport -D</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">plugins</span>: &#123;</span><br><span class="line">    <span class="string">&#x27;autoprefixer&#x27;</span>: &#123;&#125;,</span><br><span class="line">    <span class="string">&#x27;postcss-px-to-viewport&#x27;</span>: &#123; </span><br><span class="line">      <span class="attr">viewportWidth</span>: <span class="number">750</span>,    <span class="comment">// 视窗宽度，对应设计图的宽度，一般是 750 </span></span><br><span class="line">      <span class="attr">viewportHeight</span>: <span class="number">1334</span>,  <span class="comment">// 视窗高度，根据 750 设备的宽度指定，一般 1334</span></span><br><span class="line">      <span class="attr">unitPrecision</span>: <span class="number">3</span>,      <span class="comment">// 指定 px 转换为视窗单位值的小数位数（可能小数） </span></span><br><span class="line">      <span class="attr">viewportUnit</span>: <span class="string">&#x27;vw&#x27;</span>,    <span class="comment">// 指定需要转换成的视窗单位，建议使用 vw </span></span><br><span class="line">      <span class="attr">selectorBlackList</span>: [<span class="string">&#x27;.ignore&#x27;</span>, <span class="string">&#x27;.hairlines&#x27;</span>], <span class="comment">// 不转为视窗单位的类</span></span><br><span class="line">      <span class="attr">minPixelValue</span>: <span class="number">1</span>,      <span class="comment">// 小于或等于 1px 不转换为视窗单位</span></span><br><span class="line">      <span class="attr">mediaQuery</span>: <span class="literal">false</span>      <span class="comment">// 允许在媒体查询中转换 px</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">================= 二、scale：插件 v-scale-screen ===============</span><br><span class="line">.<span class="property">screen</span>-root &#123;</span><br><span class="line">    <span class="attr">height</span>: <span class="number">100</span>%;</span><br><span class="line">    <span class="attr">width</span>: <span class="number">100</span>%;</span><br><span class="line">    .<span class="property">screen</span> &#123;</span><br><span class="line">        <span class="attr">display</span>: inline-block;</span><br><span class="line">        <span class="attr">width</span>: 1920px;  <span class="comment">// 设计图宽度</span></span><br><span class="line">        <span class="attr">height</span>: 960px;  <span class="comment">// 设计图高度</span></span><br><span class="line">        transform-<span class="attr">origin</span>: <span class="number">0</span> <span class="number">0</span>;</span><br><span class="line">        <span class="attr">position</span>: absolute;</span><br><span class="line">        <span class="attr">left</span>: <span class="number">50</span>%;</span><br><span class="line">        <span class="attr">top</span>: -<span class="number">50</span>%;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;div className=<span class="string">&quot;screen-wrapper&quot;</span>&gt;</span><br><span class="line">    <span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&quot;screen&quot;</span> <span class="attr">id</span>=<span class="string">&quot;screen&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&lt;/div&gt;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">    <span class="title function_">mounted</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="comment">// 初始化自适应、绑定浏览器栏变化的自适应</span></span><br><span class="line">        <span class="title function_">handleScreenAuto</span>();</span><br><span class="line">        <span class="variable language_">window</span>.<span class="property">onresize</span> = <span class="function">() =&gt;</span> <span class="title function_">handleScreenAuto</span>();</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">deleted</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">window</span>.<span class="property">onresize</span> = <span class="literal">null</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">methods</span>: &#123;</span><br><span class="line">        <span class="title function_">handleScreenAuto</span>(<span class="params"></span>) &#123;</span><br><span class="line">            <span class="keyword">const</span> dWidth = <span class="number">1920</span>;</span><br><span class="line">            <span class="keyword">const</span> dHeight = <span class="number">960</span>;</span><br><span class="line">            <span class="keyword">const</span> clientWidth = <span class="variable language_">document</span>.<span class="property">documentElement</span>.<span class="property">clientWidth</span>;</span><br><span class="line">            <span class="keyword">const</span> cHeight = <span class="variable language_">document</span>.<span class="property">documentElement</span>.<span class="property">clientHeight</span>;</span><br><span class="line">            <span class="keyword">const</span> scale = dWidth / dHeight &gt; cWidth / cHeight ?</span><br><span class="line">            cWidth / dHeight : cWidth / dWidth;</span><br><span class="line">            <span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;#screen&#x27;</span>).<span class="property">style</span>.<span class="property">transform</span> = </span><br><span class="line">            <span class="string">`scale(<span class="subst">$&#123;scale&#125;</span>) translate(-50%, -50%)`</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">=========================== 三、rem ============================</span><br><span class="line"><span class="comment">// .postcssrc.js：获得 rem 基准值 npm i @njleonzhang/postcss-px-to-rem -D</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">plugins</span>: &#123;</span><br><span class="line">    <span class="attr">autoprefixer</span>: &#123;&#125;,</span><br><span class="line">    <span class="string">&quot;@njleonzhang/postcss-px-to-rem&quot;</span>: &#123;</span><br><span class="line">        <span class="attr">unitToConvert</span>: <span class="string">&#x27;px&#x27;</span>,        <span class="comment">// 要转换的单位，默认 px。</span></span><br><span class="line">        <span class="attr">widthOfDesignLayout</span>: <span class="number">1920</span>,  <span class="comment">// 设计布局的宽度。</span></span><br><span class="line">        <span class="attr">unitPrecision</span>: <span class="number">3</span>,           <span class="comment">// 允许 rem 单位增长到的十进制数字.</span></span><br><span class="line">        <span class="attr">selectorBlackList</span>: [<span class="string">&#x27;.ignore&#x27;</span>, <span class="string">&#x27;.hairlines&#x27;</span>], <span class="comment">// 忽略 px 选择器</span></span><br><span class="line">        <span class="attr">minPixelValue</span>: <span class="number">1</span>,           <span class="comment">// 设置要替换的最小像素值</span></span><br><span class="line">        <span class="attr">mediaQuery</span>: <span class="literal">false</span>           <span class="comment">// 允许在媒体查询中转换 px</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// rem.js：入口文件引用而实现根据比例 16:9 动态计算根元素的 font-size</span></span><br><span class="line">(<span class="keyword">function</span> <span class="title function_">init</span>(<span class="params">DesignRatio = <span class="number">16</span> / <span class="number">9</span></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> docEle = <span class="variable language_">document</span>.<span class="property">documentElement</span></span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">setHtmlFontSize</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">var</span> screenRatio = docEle.<span class="property">clientWidth</span> / docEle.<span class="property">clientHeight</span>;</span><br><span class="line">        <span class="keyword">var</span> fontSize = (screenRatio &gt; <span class="title class_">DesignRatio</span> ? </span><br><span class="line">        (<span class="title class_">DesignRatio</span> / screenRatio) : <span class="number">1</span>) * docEle.<span class="property">clientWidth</span> / <span class="number">10</span>;</span><br><span class="line">        docEle.<span class="property">style</span>.<span class="property">fontSize</span> = fontSize.<span class="title function_">toFixed</span>(<span class="number">3</span>) + <span class="string">&quot;px&quot;</span>;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(docEle.<span class="property">style</span>.<span class="property">fontSize</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">setHtmlFontSize</span>()</span><br><span class="line">    <span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&#x27;resize&#x27;</span>, setHtmlFontSize)</span><br><span class="line">&#125;)()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">================== vite 项目集成 rem =======================</span><br><span class="line"><span class="comment">// 像素单位转为 rem、浏览器前缀处理、可伸缩布局 (替代lib-flexible)</span></span><br><span class="line">npm i postcss-pxtorem autoprefixer amfe-flexible --save-dev</span><br><span class="line"><span class="comment">// main.ts/js：导入依赖</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;amfe-flexible/index.js&quot;</span>;</span><br><span class="line"><span class="comment">// postcss.config.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">plugins</span>: &#123;</span><br><span class="line">      <span class="attr">autoprefixer</span>: &#123;</span><br><span class="line">          <span class="attr">overrideBrowserslist</span>: [</span><br><span class="line">              <span class="string">&quot;Android 4.1&quot;</span>,</span><br><span class="line">              <span class="string">&quot;iOS 7.1&quot;</span>,</span><br><span class="line">              <span class="string">&quot;Chrome &gt; 31&quot;</span>,</span><br><span class="line">              <span class="string">&quot;ff &gt; 31&quot;</span>,</span><br><span class="line">              <span class="string">&quot;ie &gt;= 8&quot;</span>,</span><br><span class="line">              <span class="string">&quot;last 10 versions&quot;</span>,</span><br><span class="line">          ],</span><br><span class="line">          <span class="attr">grid</span>: <span class="literal">true</span>,</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="string">&quot;postcss-pxtorem&quot;</span>: &#123;</span><br><span class="line">          <span class="attr">rootValue</span>: <span class="number">192</span>,              <span class="comment">// 设计图宽度的 1/10</span></span><br><span class="line">          <span class="attr">propList</span>: [<span class="string">&quot;*&quot;</span>, <span class="string">&quot;!border&quot;</span>],  <span class="comment">// border 外的都转换</span></span><br><span class="line">          <span class="attr">selectorBlackList</span>: [<span class="string">&quot;.el-&quot;</span>], <span class="comment">// .el- 开头的类名不转换</span></span><br><span class="line">      &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h1 id="三、Flex-布局"><a href="#三、Flex-布局" class="headerlink" title="三、Flex 布局"></a>三、Flex 布局</h1><blockquote>
<p>如果想让一个盒子变成弹性盒子可以用 <code>display: flex</code>，弹性盒子中有主轴(横轴row) 和副轴(纵轴column)，可以根据需要设置盒子的容器(父元素)和项目(子元素)。</p>
</blockquote>
<h2 id="基础属性"><a href="#基础属性" class="headerlink" title="基础属性"></a>基础属性</h2>  <figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 容器属性</span></span><br><span class="line"><span class="selector-class">.parent</span>&#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 元素排列方向(左右和上下)，切换主副轴</span></span><br><span class="line">  <span class="attribute">flex-direction</span>: row | row-reverse | column | column-reverse;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 是否换行：reverse 往上一行换行</span></span><br><span class="line">  <span class="attribute">flex-wrap</span>: nowrap | wrap | wrap-reverse;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 复合属性，无顺序关系</span></span><br><span class="line">  <span class="attribute">flex-flow</span>: flex-direction flex-wrap; </span><br><span class="line"></span><br><span class="line">  <span class="comment">// 副轴上(即子项垂直) 的对齐方式</span></span><br><span class="line">  <span class="attribute">align-items</span>: stretch | flex-start | flex-end | center | baseline;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 主轴上(即子项水平) 的对齐方式</span></span><br><span class="line">  <span class="attribute">justify-content</span>: flex-start | flex-end | center | space-between | space-around;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 多行垂直(副轴) 对齐方式, 默认 stretch</span></span><br><span class="line">  <span class="attribute">align-content</span>: flex-start | flex-end | center | space-between | space-around;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 项目属性</span></span><br><span class="line"><span class="selector-class">.child</span>&#123;</span><br><span class="line">  <span class="comment">// 定义排列顺序, 数字越大越靠后(可为负值)</span></span><br><span class="line">  <span class="attribute">order</span>: number;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 定义放大比例 (单行有多余空间时)</span></span><br><span class="line">  <span class="attribute">flex-grow</span>: number;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 定义缩小比例 (单行空间不足时)    </span></span><br><span class="line">  <span class="attribute">flex-shrink</span>: number;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 设置主轴上项目宽度(建议代替宽度)   </span></span><br><span class="line">  <span class="attribute">flex-basis</span>: %/px/rem;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 前三者复合属性，默认0 1 auto; </span></span><br><span class="line">  <span class="attribute">flex</span>: grow [shrink] [basis];</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 定义项目自己的对齐方式，可覆盖 align-items</span></span><br><span class="line">  <span class="attribute">align-self</span>: stretch | flex-start | flex-end | center | baseline;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="布局实例"><a href="#布局实例" class="headerlink" title="布局实例"></a>布局实例</h2>  <figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// div.box、span.item</span></span><br><span class="line"><span class="selector-class">.box-1</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">justify-content</span>: center;</span><br><span class="line">  <span class="attribute">align-items</span>: center;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.box-2</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.box-3</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="selector-class">.item</span><span class="selector-pseudo">:nth-child</span>(<span class="number">2</span>) &#123;</span><br><span class="line">    <span class="attribute">align-self</span>: center;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-class">.item</span><span class="selector-pseudo">:nth-child</span>(<span class="number">3</span>) &#123;</span><br><span class="line">    <span class="attribute">align-self</span>: flex-end;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.box-4</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-flow</span>: row-reverse wrap;</span><br><span class="line">  <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">  <span class="attribute">align-content</span>: space-between;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// div.box、div.column 分别两个 span.item</span></span><br><span class="line"><span class="selector-class">.box-5</span>&#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-wrap</span>: wrap;</span><br><span class="line">  <span class="attribute">align-content</span>: space-between;</span><br><span class="line"></span><br><span class="line">  <span class="selector-class">.column</span>&#123;</span><br><span class="line">    <span class="attribute">flex-basis</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.box-6</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-wrap</span>: wrap;</span><br><span class="line">  <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">  <span class="attribute">align-content</span>: space-between;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.box-7</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-flow</span>: column wrap;</span><br><span class="line">  <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">  <span class="attribute">align-content</span>: space-between;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// div.column 分别包含 2、1、3 个子元素</span></span><br><span class="line"><span class="selector-class">.box-8</span>&#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-wrap</span>: wrap;</span><br><span class="line">  <span class="attribute">align-content</span>: space-between;</span><br><span class="line"></span><br><span class="line">  <span class="selector-class">.column</span>&#123;</span><br><span class="line">    <span class="attribute">flex-basis</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-class">.column</span><span class="selector-pseudo">:nth-child</span>(<span class="number">2</span>)&#123;</span><br><span class="line">    <span class="attribute">justify-content</span>: center;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

  <div align="center">
      <img src="" data-original="/images/mobile/flex.png" alt="flex 布局" width="100%">
  </div>


<h2 id="网格布局"><a href="#网格布局" class="headerlink" title="网格布局"></a>网格布局</h2><blockquote>
<p>平均分布，即在容器里面平均分配空间</p>
</blockquote>
  <figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 几个子元素就平分几份</span></span><br><span class="line"><span class="selector-class">.box</span>&#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="selector-class">.item</span>&#123;</span><br><span class="line">    <span class="attribute">flex</span>: <span class="number">1</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 某个网格的宽度为固定的百分比，其余网格平均分配剩余的空间</span></span><br><span class="line"><span class="selector-class">.box</span>&#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="selector-class">.item</span>&#123;</span><br><span class="line">    <span class="comment">// flex: 1 1 0%;</span></span><br><span class="line">    <span class="attribute">flex</span>: <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    &amp;<span class="selector-class">.fixed</span>&#123;</span><br><span class="line">      <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">20%</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="圣杯布局"><a href="#圣杯布局" class="headerlink" title="圣杯布局"></a>圣杯布局</h2>  <figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span>&#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">min-height</span>: <span class="number">100vh</span>;</span><br><span class="line">  <span class="attribute">flex-direction</span>: column;</span><br><span class="line"></span><br><span class="line">  <span class="selector-tag">header</span>, <span class="selector-tag">footer</span> &#123;</span><br><span class="line">    <span class="attribute">flex</span>: <span class="number">1</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="selector-class">.content</span>&#123;</span><br><span class="line">    <span class="attribute">flex</span>: <span class="number">1</span>;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    </span><br><span class="line">    <span class="selector-class">.main</span>&#123;</span><br><span class="line">      <span class="attribute">flex</span>: <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="selector-class">.left</span>, <span class="selector-class">.right</span>&#123;</span><br><span class="line">      <span class="comment">// 两个边栏的宽度设为 12em</span></span><br><span class="line">      <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">12em</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="selector-class">.left</span>&#123;</span><br><span class="line">      <span class="attribute">order</span>: -<span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 小屏幕时内容区三栏自动变为垂直叠加</span></span><br><span class="line"><span class="keyword">@media</span> (<span class="attribute">max-width</span>: <span class="number">768px</span>) &#123;</span><br><span class="line">  <span class="selector-class">.content</span> &#123;</span><br><span class="line">    <span class="attribute">flex-direction</span>: column;</span><br><span class="line">    <span class="attribute">flex</span>: <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="selector-class">.left</span>, <span class="selector-class">.main</span>, <span class="selector-class">.right</span> &#123;</span><br><span class="line">      <span class="attribute">flex</span>: auto;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

  <div align="center">
      <img src="" data-original="/images/mobile/grail.png" alt="圣杯布局" width="100%">
  </div>


<h2 id="流式布局"><a href="#流式布局" class="headerlink" title="流式布局"></a>流式布局</h2><blockquote>
<p>每行的项目数固定，会自动分行</p>
</blockquote>
  <figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.parent</span> &#123;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">150px</span>;</span><br><span class="line">  <span class="attribute">background-color</span>: black;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-flow</span>: row wrap;</span><br><span class="line">  <span class="attribute">align-content</span>: flex-start;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.child</span> &#123;</span><br><span class="line">  <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">  <span class="attribute">background-color</span>: white;</span><br><span class="line">  <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">25%</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">50px</span>;</span><br><span class="line">  <span class="attribute">border</span>: <span class="number">1px</span> solid red;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="固定底栏"><a href="#固定底栏" class="headerlink" title="固定底栏"></a>固定底栏</h2><blockquote>
<p>页面内容太少时底栏会抬高到页面的中间，移动端 fixed 定位会导致输入内容的虚拟键盘会导致定位元素错位等问题</p>
</blockquote>
  <figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span>&#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100vh</span>;</span><br><span class="line">  <span class="attribute">flex-direction</span>: column;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// header、footer、div.content</span></span><br><span class="line">  <span class="selector-class">.content</span>&#123;</span><br><span class="line">    <span class="attribute">flex</span>: <span class="number">1</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">height</span>: auto;</span><br><span class="line">    <span class="attribute">overflow-y</span>: scroll;</span><br><span class="line">    -webkit-<span class="attribute">overflow</span>-scrolling: touch;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 隐藏滚动条</span></span><br><span class="line">::-webkit-scrollbar&#123;  </span><br><span class="line">    <span class="attribute">width</span>: <span class="number">0px</span>; </span><br><span class="line">    <span class="attribute">height</span>: <span class="number">0px</span>;</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="number">#fff</span>;  </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// absolute 方式</span></span><br><span class="line"><span class="selector-class">.box</span>&#123;</span><br><span class="line">  <span class="attribute">position</span>: relative;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line"></span><br><span class="line">  <span class="selector-class">.content</span>&#123;</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">left</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">right</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">top</span>: <span class="number">100px</span>;</span><br><span class="line">    <span class="attribute">bottom</span>: <span class="number">100px</span>;</span><br><span class="line">    <span class="attribute">height</span>: auto;</span><br><span class="line">    <span class="attribute">overflow-y</span>: scroll;</span><br><span class="line">    -webkit-<span class="attribute">overflow</span>-scrolling: touch;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-tag">footer</span>&#123;</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">left</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">right</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">bottom</span>: <span class="number">0</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="样式布局"><a href="#样式布局" class="headerlink" title="样式布局"></a>样式布局</h2>  <figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 输入框的前方添加提示，后方添加按钮</span></span><br><span class="line"><span class="selector-class">.input-item</span>&#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="selector-tag">input</span>&#123;</span><br><span class="line">    <span class="attribute">flex</span>: <span class="number">1</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 主栏的左侧或右侧添加一个图片栏 (类似头像)</span></span><br><span class="line"><span class="selector-class">.item</span>&#123;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">align-items</span>: flex-start;</span><br><span class="line">  <span class="selector-tag">img</span>&#123;</span><br><span class="line">    <span class="attribute">margin-right</span>: <span class="number">1em</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-tag">p</span>&#123;</span><br><span class="line">    <span class="attribute">flex</span>: <span class="number">1</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 两端对齐，列不满时左对齐</span></span><br><span class="line"><span class="comment">// 法一：如果每行有 n 项，则在最后添加 n-2 个空项</span></span><br><span class="line"><span class="selector-tag">ul</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">flex-wrap</span>: wrap;</span><br><span class="line">    <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">  <span class="selector-tag">li</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">30%</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">50px</span>;</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="number">#f1f8ff</span>;</span><br><span class="line">    <span class="attribute">margin-bottom</span>: <span class="number">10px</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-tag">li</span><span class="selector-class">.empty</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">30%</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">0px</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 法二；利用 after/before，适用于每行 3/4 项</span></span><br><span class="line"><span class="selector-tag">ul</span><span class="selector-pseudo">:after</span> &#123;</span><br><span class="line">  <span class="attribute">display</span>:block;</span><br><span class="line">  <span class="attribute">content</span>:<span class="string">&quot;&quot;</span>;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">30%</span>;</span><br><span class="line">  <span class="attribute">height</span>:<span class="number">0px</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h1 id="四、事件类型"><a href="#四、事件类型" class="headerlink" title="四、事件类型"></a>四、事件类型</h1><h2 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h2><ul>
<li><strong>click</strong>：单击事件。移动端中连续 click 的触发有 200~300ms 的延迟，延迟来自判断双击和长按，因为只有默认等待时间结束以确定没有后续动作发生时才会触发 click 事件。所以触摸事件反应更快，体验更好，也可以通过 fastclick 库解决延迟问题。</li>
<li><strong>touch</strong>：触摸类事件，分为四种触发方式：touchstart (触屏开始)、touchmove (拖拽)、touchend (触屏完成)、touchcancel (触屏取消)。触屏时如果有更高级别的事件发生，比如电话接入或弹出信息等，则触发 ontouchcancel 事件。</li>
<li><strong>gesture</strong>：手势类事件，可分为三种：gesturestart (两&#x2F;多根手指按下时)、gesturechange (两&#x2F;多根手指按下且移动时)、gestureend (倒数第二根手指移开时)。手势的专有属性有：rotation (手指变化引起的旋转角度)、scale (手指之间的距离)。</li>
<li><strong>tap</strong>：触碰类事件，一般用于代替 click 事件，分为四种：tap (手指触碰屏幕)、longTap (手指长按屏幕)、singleTap (手指单击屏幕)、doubleTap(手指双击屏幕)。</li>
<li><strong>swipe</strong>：滑动事件，分为五种：swipe (滑动手指)、swipeLeft (左滑)、swipeRight (右滑)、swipeUp (上滑)、swipeDown (下滑)。</li>
</ul>
<h2 id="触发"><a href="#触发" class="headerlink" title="触发"></a>触发</h2>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 触发顺序：ontouchstart、ontouchmove、ontouchend、onclick</span></span><br><span class="line"><span class="title function_">addEvent</span>(dom, <span class="string">&#x27;tap click touchstart touchmove&#x27;</span>, <span class="literal">false</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">addEvent</span>(<span class="params">dom, type, showAll</span>) &#123;</span><br><span class="line">    type = type.<span class="title function_">split</span>(<span class="string">&#x27; &#x27;</span>)</span><br><span class="line">    type.<span class="title function_">forEach</span>(<span class="keyword">function</span>(<span class="params">item</span>) &#123;</span><br><span class="line">        dom.<span class="title function_">addEventListener</span>(item, <span class="keyword">function</span>(<span class="params">v</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(showAll ? v : v.<span class="property">type</span>)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h3 id="事件对象"><a href="#事件对象" class="headerlink" title="事件对象"></a>事件对象</h3><ul>
<li>获取：box.addEventListener(“touchstart”, function(event){ },true)。</li>
<li>属性<ul>
<li>touches：当前跟踪的触摸操作的 touch 对象的数组。</li>
<li>targetTouches：特定于事件目标的 touch 对象数组 (事件冒泡指出目标对象)。</li>
<li>changedTouches：表示自上次触摸以来发生了什么改变的 touch 对象的数组。</li>
</ul>
</li>
<li>特点<ul>
<li>touchend 事件时 touches、targetTouches 信息会被删除，changedTouches 保存最后一次的信息，最好用于计算手指信息。</li>
<li>通过 jquery 不能获取以上三个属性，而通过 zepto.js (精简版的 jquery，现在用的不多) 可以正常获取。</li>
</ul>
</li>
</ul>
<h2 id="问题方案"><a href="#问题方案" class="headerlink" title="问题方案"></a>问题方案</h2><h3 id="click-延迟"><a href="#click-延迟" class="headerlink" title="click 延迟"></a>click 延迟</h3><blockquote>
<p>原因：移动端浏览器会优先判断用户是否要触发双击缩放、双击滚动等默认行为，用户碰触页面后需要等待 300ms 左右来判断是不是双击动作而不是立即响应。</p>
</blockquote>
<ul>
<li>设置 device-width：<meta name="viewport" content="width=device-width">&#96;。</li>
<li>禁用缩放：<code>&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, user-scalable=no&quot;&gt;</code>。</li>
<li>FastClick：<code>import fastclick from &#39;fastclick&#39;、fastclick.attach(document.body)</code>。</li>
<li>CSS touch-action：<code>touch-action: none</code>，表示在该元素上的操作不会触发用户代理的任何默认行为。</li>
</ul>
<h3 id="点击穿透"><a href="#点击穿透" class="headerlink" title="点击穿透"></a>点击穿透</h3><blockquote>
<p>原生 touch 事件、框架的自定义 tap 事件都存在该问题，因为 touch 系列事件发生大约 300ms 后才会触发 click 事件。</p>
</blockquote>
<ul>
<li>出现问题<ul>
<li>点击蒙层上的关闭按钮，蒙层消失后发现触发了按钮下面元素的 click 事件，如果有 a 标签则会触发页面跳转。</li>
<li>直接点击页面内按钮跳转至新页面，然后发现新页面中对应位置元素的 click 事件被触发。</li>
</ul>
</li>
<li>解决方案<ul>
<li>不要混用 touch、click：只用一种事件就不会存在点击穿透问题。</li>
<li>fastclick：引入库之后把页面内所有 touch 事件都换为 click。</li>
<li>pointer-events： 不建议使用 mask 隐藏后，给按钮下面元素添加 <code>pointer-events: none;</code>。</li>
<li>阻止默认：<code>&lt;div class=&quot;mask&quot; @touchmove.prevent&gt;&lt;/div&gt;、&lt;div ontouchend = &quot;e.preventDefault()&quot;&gt;&lt;/div&gt;</code>。</li>
</ul>
</li>
</ul>
<h3 id="touch、mouse"><a href="#touch、mouse" class="headerlink" title="touch、mouse"></a>touch、mouse</h3>  <div style="text-indent: 2em">移动端中只有触屏事件完成后再次触发时，才会触发上一个事件的 mouseout 事件。即系统会在手指提起的瞬间判断接收到事件的元素是否被改变，若没有改变则会按照 mousedown、mouseup、click 的顺序依次触发，反之不会触发。</div>
 

<h3 id="点击状态处理"><a href="#点击状态处理" class="headerlink" title="点击状态处理"></a>点击状态处理</h3><ul>
<li>hover 样式：移动端不可用。</li>
<li>touch 事件：动态增删 class 或绑定动画。</li>
<li>激活状态：常用于 a、button 等元素的伪类 :active<ul>
<li>js：<code>document.body.addEventListener(&#39;touchstart&#39;, fn)</code></li>
<li>html：<code>body ontouchstart</code></li>
</ul>
</li>
<li>点击高亮：<code>a &#123; tap-highlight-color: transparent; &#125;</code></li>
</ul>
<h3 id="touch、gesture"><a href="#touch、gesture" class="headerlink" title="touch、gesture"></a>touch、gesture</h3><ul>
<li>当一个手指放在屏幕上时会触发 touchstart 事件，如果另一个手指又放到了屏幕上则会触发 gesturestart 事件，然后触发基于该手指的 touchstart 事件。</li>
<li>如果两个手指在屏幕上滑动将会触发 gesturechange 事件，但只要有一个手指移开则会触发 gestureend 事件，然后又触发 touchend 事件。</li>
</ul>

    </div>

    
    
    <div>
      
        <div>
    
        <div style="text-align:center;color: #ccc;font-size:14px;margin-top:20px;">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div>
    
</div>

      
    </div>
    
        

<div>
<ul class="post-copyright">
  <li class="post-copyright-author">
    <strong>本文作者： </strong>chuangges
  </li>
  <li class="post-copyright-link">
    <strong>本文链接：</strong>
    <a href="https://chuangges.gitee.io/2019/06/24/8-1-%E7%A7%BB%E5%8A%A8%E7%AB%AF%E5%BC%80%E5%8F%91/" title="移动端开发">https://chuangges.gitee.io/2019/06/24/8-1-移动端开发/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/zh_CN" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>


      <footer class="post-footer">

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2019/06/20/7-2-Node%E6%A1%86%E6%9E%B6/" rel="prev" title="Node.js 常用框架">
      <i class="fa fa-chevron-left"></i> Node.js 常用框架
    </a></div>
      <div class="post-nav-item">
    <a href="/2019/06/28/8-4-%E7%A7%BB%E5%8A%A8%E7%AB%AF%E9%9A%BE%E7%82%B9/" rel="next" title="移动端技术难点">
      移动端技术难点 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81%E5%BC%80%E5%8F%91%E6%8A%80%E6%9C%AF"><span class="nav-number">1.</span> <span class="nav-text">一、开发技术</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BA%94%E7%94%A8%E7%B1%BB%E5%9E%8B"><span class="nav-number">1.1.</span> <span class="nav-text">应用类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B7%A8%E5%B9%B3%E5%8F%B0%E6%96%B9%E6%A1%88"><span class="nav-number">1.2.</span> <span class="nav-text">跨平台方案</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#WebView"><span class="nav-number">1.3.</span> <span class="nav-text">WebView</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#JSBridge"><span class="nav-number">1.4.</span> <span class="nav-text">JSBridge</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81%E9%80%82%E9%85%8D%E6%96%B9%E6%A1%88"><span class="nav-number">2.</span> <span class="nav-text">二、适配方案</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Viewport-%E7%BC%A9%E6%94%BE"><span class="nav-number">2.1.</span> <span class="nav-text">Viewport 缩放</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Responsive-%E5%93%8D%E5%BA%94%E5%BC%8F"><span class="nav-number">2.2.</span> <span class="nav-text">Responsive 响应式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Adaptive-%E8%87%AA%E9%80%82%E5%BA%94"><span class="nav-number">2.3.</span> <span class="nav-text">Adaptive 自适应</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81Flex-%E5%B8%83%E5%B1%80"><span class="nav-number">3.</span> <span class="nav-text">三、Flex 布局</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E7%A1%80%E5%B1%9E%E6%80%A7"><span class="nav-number">3.1.</span> <span class="nav-text">基础属性</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B8%83%E5%B1%80%E5%AE%9E%E4%BE%8B"><span class="nav-number">3.2.</span> <span class="nav-text">布局实例</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%BD%91%E6%A0%BC%E5%B8%83%E5%B1%80"><span class="nav-number">3.3.</span> <span class="nav-text">网格布局</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9C%A3%E6%9D%AF%E5%B8%83%E5%B1%80"><span class="nav-number">3.4.</span> <span class="nav-text">圣杯布局</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%B5%81%E5%BC%8F%E5%B8%83%E5%B1%80"><span class="nav-number">3.5.</span> <span class="nav-text">流式布局</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9B%BA%E5%AE%9A%E5%BA%95%E6%A0%8F"><span class="nav-number">3.6.</span> <span class="nav-text">固定底栏</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A0%B7%E5%BC%8F%E5%B8%83%E5%B1%80"><span class="nav-number">3.7.</span> <span class="nav-text">样式布局</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B%E3%80%81%E4%BA%8B%E4%BB%B6%E7%B1%BB%E5%9E%8B"><span class="nav-number">4.</span> <span class="nav-text">四、事件类型</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%88%86%E7%B1%BB"><span class="nav-number">4.1.</span> <span class="nav-text">分类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%A7%A6%E5%8F%91"><span class="nav-number">4.2.</span> <span class="nav-text">触发</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BA%8B%E4%BB%B6%E5%AF%B9%E8%B1%A1"><span class="nav-number">4.2.1.</span> <span class="nav-text">事件对象</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%97%AE%E9%A2%98%E6%96%B9%E6%A1%88"><span class="nav-number">4.3.</span> <span class="nav-text">问题方案</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#click-%E5%BB%B6%E8%BF%9F"><span class="nav-number">4.3.1.</span> <span class="nav-text">click 延迟</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%82%B9%E5%87%BB%E7%A9%BF%E9%80%8F"><span class="nav-number">4.3.2.</span> <span class="nav-text">点击穿透</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#touch%E3%80%81mouse"><span class="nav-number">4.3.3.</span> <span class="nav-text">touch、mouse</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%82%B9%E5%87%BB%E7%8A%B6%E6%80%81%E5%A4%84%E7%90%86"><span class="nav-number">4.3.4.</span> <span class="nav-text">点击状态处理</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#touch%E3%80%81gesture"><span class="nav-number">4.3.5.</span> <span class="nav-text">touch、gesture</span></a></li></ol></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="chuangges" src="" data-original="/images/chuang.png">
  <p class="site-author-name" itemprop="name">chuangges</p>
  <div class="site-description" itemprop="description">chuangge's blog.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">39</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/chuangges" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;chuangges" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://stackoverflow.com/yourname" title="StackOverflow → https:&#x2F;&#x2F;stackoverflow.com&#x2F;yourname" rel="external nofollow noopener noreferrer" target="_blank"><i class="fab fa-stack-overflow fa-fw"></i>StackOverflow</a>
      </span>
  </div>


  <div class="links-of-blogroll motion-element">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://juejin.im/" title="https:&#x2F;&#x2F;juejin.im&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">掘金</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.nowcoder.com/" title="https:&#x2F;&#x2F;www.nowcoder.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">牛客网</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://www.docschina.org/" title="https:&#x2F;&#x2F;www.docschina.org&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">印记中文</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="http://tool.lu/" title="http:&#x2F;&#x2F;tool.lu&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">在线工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tinypng.com/" title="https:&#x2F;&#x2F;tinypng.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片压缩</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://bigjpg.com/" title="https:&#x2F;&#x2F;bigjpg.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">图片放大</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://tool.chinaz.com/" title="https:&#x2F;&#x2F;tool.chinaz.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">站长工具</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://learn-anything.xyz/" title="https:&#x2F;&#x2F;learn-anything.xyz&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Learn-Anything</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://stackoverflow.com/" title="https:&#x2F;&#x2F;stackoverflow.com&#x2F;" rel="external nofollow noopener noreferrer" target="_blank">Stack-Overflow</a>
        </li>
    </ul>
  </div>

      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2024</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">chuangge</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-area"></i>
    </span>
    <span title="站点总字数">1m</span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
    <span title="站点阅读时长">15:14</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="external nofollow noopener noreferrer" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"jsonPath":"/live2dw/assets/tororo.model.json"},"display":{"position":"left","width":180,"height":360},"mobile":{"show":false},"react":{"opacityDefault":1,"opacityOnHover":1},"log":false,"tagMode":false});</script>
        <style>
            [bg-lazy] {
                background-image: none !important;
                background-color: #eee !important;
            }
        </style>
        <script>
            window.imageLazyLoadSetting = {
                isSPA: false,
                preloadRatio: 1,
                processImages: null,
            };
        </script><script>window.addEventListener("load",function(){var t=/\.(gif|jpg|jpeg|tiff|png)$/i,r=/^data:image\/[a-z]+;base64,/;Array.prototype.slice.call(document.querySelectorAll("img[data-original]")).forEach(function(a){var e=a.parentNode;"A"===e.tagName&&(e.href.match(t)||e.href.match(r))&&(e.href=a.dataset.original)})});</script><script>!function(e){e.imageLazyLoadSetting.processImages=t;var n=e.imageLazyLoadSetting.isSPA,i=e.imageLazyLoadSetting.preloadRatio||1,r=o();function o(){var t=Array.prototype.slice.call(document.querySelectorAll("img[data-original]")),e=Array.prototype.slice.call(document.querySelectorAll("[bg-lazy]"));return t.concat(e)}function t(){n&&(r=o());for(var t,a=0;a<r.length;a++)0<=(t=(t=r[a]).getBoundingClientRect()).bottom&&0<=t.left&&t.top<=(e.innerHeight*i||document.documentElement.clientHeight*i)&&function(){var t,e,n,i,o=r[a];e=function(){r=r.filter(function(t){return o!==t})},(t=o).hasAttribute("bg-lazy")?(t.removeAttribute("bg-lazy"),e&&e()):(n=new Image,i=t.getAttribute("data-original"),n.onload=function(){t.src=i,t.removeAttribute("data-original"),e&&e()},t.src!==i&&(n.src=i))}()}function a(){clearTimeout(t.tId),t.tId=setTimeout(t,500)}t(),document.addEventListener("scroll",a),e.addEventListener("resize",a),e.addEventListener("orientationchange",a)}(this);</script></body>
</html>
